package common.security;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description: 初始化敏感词库，将敏感词加入到HashMap中，构建DFA算法模型
 * @Author : chenjiade
 * @Date ： 2014年8月14日
 * @version 1.0
 */
public class SensitivewordFilter {

	private final static int MATCHTYPE = 1; //最小匹配规则
	private final static String REGEX="[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？《》〈〉  ]";  
	
	private String encoding = "UTF8";   //
	private String txtName = "D:\\SensitiveWord.txt";

	private HashMap<String, String> sensitiveWordMap;
	
	public SensitivewordFilter(){
		this.initKeyWord();
	}
	public SensitivewordFilter(String txtName){
		this.txtName = txtName;
		this.initKeyWord();
	}

	public SensitivewordFilter(String txtName,String encoding){
		this.txtName = txtName;
		this.encoding = encoding;
		this.initKeyWord();
	}
	public SensitivewordFilter(Set<String> keyWordSet){
		addSensitiveWordToHashMap(keyWordSet);
	}
	private void initKeyWord(){
		try {
			Set<String> keyWordSet = readSensitiveWordFile();
	
			addSensitiveWordToHashMap(keyWordSet);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	
	
	public int getSensitiveWordSize() {
		return sensitiveWordMap.size();
	}
	/**
	 * 读取敏感词库，将敏感词放入HashSet中，构建一个DFA算法模型：
	 * @Author : chenjiade
	 * @Date ： 2014年8月14日
	 * @param keyWordSet  敏感词库
	 * @version 1.0
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void addSensitiveWordToHashMap(Set<String> keyWordSet) {
		sensitiveWordMap = new HashMap<String, String>(keyWordSet.size());    
		String key = null;  
		Map nowMap = null;
		Map<String, String> newWorMap = null;
		
		Iterator<String> iterator = keyWordSet.iterator();
		while(iterator.hasNext()){
			key = (String) iterator.next();   
			nowMap = sensitiveWordMap;
			for(int i = 0 ; i < key.length() ; i++){
				char keyChar = key.charAt(i);    
				Object wordMap = nowMap.get(keyChar+"");      
				
				if(wordMap != null){    
					nowMap = (Map<String, String>) wordMap;
				}
				else{    
					newWorMap = new HashMap<String, String>();
					newWorMap.put("isEnd", "0");  
					nowMap.put(keyChar+"", newWorMap);
					nowMap = newWorMap;
				}
				
				if(i == key.length() - 1){
					nowMap.put("isEnd", "1");    
				}
			}
		}
	}

	/**
	 * 读取敏感词库中的内容，将内容添加到set集合中
	 * @Author : chenjiade
	 * @Date ： 2014年8月14日
	 * @return
	 * @version 1.0
	 * @throws Exception 
	 */
	private Set<String> readSensitiveWordFile() throws Exception{
		Set<String> set = null;
		
		File file = new File(txtName); 
		InputStreamReader read = new InputStreamReader(new FileInputStream(file),encoding);
		try {
			if(file.isFile() && file.exists()){    
				set = new HashSet<String>();
				BufferedReader bufferedReader = new BufferedReader(read);
				String txt = null;
				while((txt = bufferedReader.readLine()) != null){    
					set.add(txt);
			    }
				bufferedReader.close();
			}
			else{ 
				throw new Exception("文件读取错误......");
			}
		} catch (Exception e) {
			throw e;
		}finally{
			read.close();     
		}
		return set;
	}
	
	/**
	 * 获取文字中的敏感词
	 * @Author : chenjiade
	 * @Date ： 2014年8月14日
	 * @param txt 文字
	 * @param matchType 匹配规则&nbsp;1：最小匹配规则，2：最大匹配规则
	 * @return
	 * @version 1.0
	 */
	public Set<String> getSensitiveWord(String txt , int matchType){
		Set<String> sensitiveWordList = new HashSet<String>();
		Matcher  matcher =  Pattern.compile(REGEX).matcher(txt); 
        txt = matcher.replaceAll("").trim();
		for(int i = 0 ; i < txt.length() ; i++){
			int length = CheckSensitiveWord(txt, i, matchType);   
			if(length > 0){   
				sensitiveWordList.add(txt.substring(i, i+length));
				i = i + length - 1;  
			}
		}
		
		return sensitiveWordList;
	}
	
	/**
	 * 判断文字是否包含敏感字符
	 * @Author : chenjiade
	 * @Date ： 2014年8月14日
	 * @param txt  文字
	 * @param matchType  匹配规则&nbsp;1：最小匹配规则，2：最大匹配规则
	 * @return 若包含返回true，否则返回false
	 * @version 1.0
	 */
	@SuppressWarnings("rawtypes")
	private int CheckSensitiveWord(String txt,int beginIndex,int matchType){
		boolean  flag = false;   
		int matchFlag = 0;     
		char word = 0;
		Map nowMap = sensitiveWordMap;
		for(int i = beginIndex; i < txt.length() ; i++){
			word = txt.charAt(i);
			nowMap = (Map) nowMap.get(word+"");   
			if(nowMap != null){    
				matchFlag++;    
				if("1".equals(nowMap.get("isEnd"))){      
					flag = true;       
					if(MATCHTYPE == matchType){   
						break;
					}
				}
			}
			else{   
				break;
			}
		}
		if(matchFlag < 2 || !flag){       
			matchFlag = 0;
		}
		return matchFlag;
	}
}
